﻿#include "metaproperty.h"
#include "metasignal.h"
#include "metainfo.h"

MetaProperty::MetaProperty(IMetaInfoBackend *meta, int idx)
{
    this->meta = meta? meta->shared_from_this():NULL;
    this->idx = idx;

	localMeta = IMetaInfoBackend::ToLocalProperty(idx,meta,localIdx);
}

MetaProperty::MetaProperty()
{
    idx = 0;
	localIdx = 0;
	localMeta = NULL;
}

MetaInfo MetaProperty::EnclosingMetaInfo() const
{
	return MetaInfo(meta.get());
}

int MetaProperty::Index() const
{
    return idx;
}

bool MetaProperty::isValid() const
{
    return (bool)meta;
}

std::string MetaProperty::Name() const
{
    if(!isValid())
    {
        return "";
    }

	
    auto info = LocalMeta()->GetPropertyInfo(LocalIndex());

	return info.Name;
}

bool MetaProperty::isStatic() const
{
    if(!isValid())
    {
        return false;
    }
	auto info = LocalMeta()->GetPropertyInfo(LocalIndex());

	return info.flags & MetaPropertyInfo::Static;
}

bool MetaProperty::isReadable() const
{
    if(!isValid())
    {
        return false;
    }

	auto info = LocalMeta()->GetPropertyInfo(LocalIndex());

	return info.Readable;
}

bool MetaProperty::isWritable() const
{
	if (!isValid())
	{
		return false;
	}

	auto info = LocalMeta()->GetPropertyInfo(LocalIndex());

	return info.Writable;
}

bool MetaProperty::hasNotifier() const
{
    if(!isValid())
    {
        return false;
    }

	auto info = LocalMeta()->GetPropertyInfo(LocalIndex());

	return !info.NotifierName.empty();
}

MetaTypeId MetaProperty::Type() const
{
    if(!isValid())
    {
        return MetaType::BT_None;
    }

	auto info = LocalMeta()->GetPropertyInfo(LocalIndex());

	return info.Type;
}

Variant MetaProperty::GetValue(const void *o) const
{
    if(!isValid())
    {
        return Variant();
    }

    if(!isReadable()){
        return Variant();
    }

	auto info = LocalMeta()->GetPropertyInfo(LocalIndex());

	Variant ret = Variant::FromType(info.Type);

	LocalMeta()->ReadProperty(const_cast<void*>(o), LocalIndex(), ret.data());

	return ret;
}

void MetaProperty::SetValue(void* o,Variant value) const
{
    if(!isValid())
    {
        return;
    }

    if(!isWritable()){
        return;
    }

	auto info = LocalMeta()->GetPropertyInfo(LocalIndex());

	if (!value.Convertable(info.Type)) {
		return;
	}

	value.Convert(info.Type);

	LocalMeta()->WriteProperty(o, LocalIndex(), value.data());
}

MetaSignal MetaProperty::GetNotifier() const
{
    if(!isValid())
    {
        return MetaSignal();
    }

    if(!hasNotifier()){
        return MetaSignal();
    }
	
	auto info = LocalMeta()->GetPropertyInfo(LocalIndex());
	MetaInfo m(meta.get());
	for (int i = 0; i < m.SignalCount(); i++) {
		auto sig = m.GetSignal(i);
		if (sig.Name() == info.NotifierName) {
			return sig;
		}
	}

	return MetaSignal();
}

std::vector<std::string> MetaProperty::GetPropertyInfo() const
{
    if(!isValid())
    {
        return std::vector<std::string>();
    }

	auto info = LocalMeta()->GetPropertyInfo(LocalIndex());
	return info.Infos;
}

IMetaInfoBackend * MetaProperty::LocalMeta() const
{
	return localMeta;
}

int MetaProperty::LocalIndex() const
{
	return localIdx;
}
